﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Acoris.Rendering
{
    using System.Numerics;

    /// <summary>
    /// represents a visual element
    /// </summary>
    public abstract class VisualElement : IDisposable
    {
        // VisualElement
        //
        // 1) 维护可视化元素的尺寸信息
        // 2) 维护可视化元素的可视化信息
        // 3) 维护可视化元素的位置信息
        // 4) 维护可视化元素的父节点信息
        // 5) 维护可视化元素的状态信息
        // 6) 维护可视化元素的样式信息
        // 7) 维护可视化元素

        // 维护VisualElement的渲染大小信息
        // Width、Height属性只有元素指定了具体大小时才会生效
        // ActualWidth、ActualHeight属性是渲染过程中唯一依赖的属性

        /// <summary>
        /// gets a value that value indicate the size is auto
        /// </summary>
        public const float Auto = -1;

        /// <summary>
        /// gets zero value margin instance
        /// </summary>
        public static readonly Thickness ZeroMargin = default(Thickness);

        private bool hasCached;
        private bool hasChanged;

        #region Boundary

        /// <summary>
        /// gets or sets width
        /// </summary>
        public float Width { get; set; } = Auto;

        /// <summary>
        /// gets or sets height
        /// </summary>
        public float Height { get; set; } = Auto;

        /// <summary>
        /// gets or sets actual width
        /// </summary>
        public float ActualWidth { get; set; } = Auto;

        /// <summary>
        /// gets or sets actual height
        /// </summary>
        public float ActualHeight { get; set; } = Auto;

        /// <summary>
        /// gets or sets thickness
        /// </summary>
        public Thickness Margin { get; set; } = ZeroMargin;

        /// <summary>
        /// gets or sets min height
        /// </summary>
        public float MinHeight { get; set; } = Auto;

        /// <summary>
        /// gets or set min width
        /// </summary>
        public float MinWidth { get; set; } = Auto;

        #endregion

        #region Visual

        // 维护VisualElement的可视化信息
        // 维护VisualElement的状态信息
        // 

        /// <summary>
        /// gets or sets visibility
        /// </summary>
        public Visibility Visibility { get; set; } = Visibility.Visible;

        /// <summary>
        /// gets or sets opacity
        /// </summary>
        public float Opacity { get; set; } = 1.0f;

        /// <summary>
        /// gets or sets background brush
        /// </summary>
        public Brush Background { get; set; }

        /// <summary>
        /// gets or sets vertical alignment
        /// </summary>
        public VerticalAlignment VerticalAlignment { get; set; } = VerticalAlignment.Auto;

        /// <summary>
        /// gets or sets horizontal alignment
        /// </summary>
        public HorizontalAlignment HorizontalAlignment { get; set; } = HorizontalAlignment.Auto;

        /// <summary>
        /// gets or sets device query Result
        /// </summary>
        public DeviceQuery DeviceQuery { get; set; } = DeviceQuery.PC;

        /// <summary>
        /// gets Visual State
        /// </summary>
        public VisualState VisualState { get; internal set; }

        /// <summary>
        /// gets or sets trigger array
        /// </summary>
        public IList<TriggerBase> Triggers { get; private set; } = new List<TriggerBase>();

        /// <summary>
        /// gets or sets ZIndex
        /// </summary>
        public int ZIndex { get; set; } = 1;
        #endregion

#if FEATURE_1_1

        /// <summary>
        /// gets or sets clip rectangle area
        /// </summary>
        public Vector4 Clip { get; set; }

#endif

        /// <summary>
        /// gets or sets parent node
        /// </summary>
        public VisualElement Parent { get; set; }


        // there are four condition
        // 1) HasChanged = true HasCached = true
        //    we should disposed resource which created last time rendering
        // 2) HasChanged = true HasCached = false
        //    we should cached all rendering-resource when we want to rendering
        // 3) HasChanged = false HasCached = true
        //    ship preparation procedure
        // 4) HasChanged = false HasCached = false
        //    damn it! it must be something errors raised

        /// <summary>
        /// gets a value that value indicated whether this element content changed
        /// </summary>
        public bool HasChanged {
            get { return hasChanged; }
        }

        /// <summary>
        /// gets a value that value indicated whether this element has been cached
        /// </summary>
        public bool HasCached {
            get { return hasCached; }
        }

        /// <summary>
        /// begin change action
        /// </summary>        
        protected void BeginChange() {
            hasChanged = true;
        }

        /// <summary>
        /// 
        /// </summary>
        protected void Cache() {
            hasCached = true;
        }

        /// <summary>
        /// end change action
        /// </summary>
        protected void EndChange() {
            hasChanged = false;
        }

        /// <summary>
        /// disposed all rendering-resources
        /// </summary>
        public virtual void Dispose() {
            hasCached = false;
        }
    }
}
